www.gusucode.com > VC++ 特殊网址访问器源代码-源码程序 > VC++ 特殊网址访问器源代码-源码程序/code/Demo3/SaveScrJpg.cpp

    //Download by http://www.NewXing.com
// SaveScrJpg.cpp: implementation of the SaveScrJpg class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "SaveScrJpg.h"
#include "math.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

HANDLE SaveScrJpg::DDBToDIB( HBITMAP hBitmap, DWORD dwCompression, HPALETTE hPal )
{
	BITMAP			bm;
	BITMAPINFOHEADER	bi;
	LPBITMAPINFOHEADER 	lpbi;
	DWORD			dwLen;
	HANDLE			hDIB;
	HANDLE			handle;
	HDC 			hDC;
	
	ASSERT( hBitmap );
	// The function has no arg for bitfields
	if( dwCompression == BI_BITFIELDS )
		return NULL;

	// If a palette has not been supplied use defaul palette
	if (hPal==NULL)
		hPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE);
	
	// Get bitmap information
	::GetObject(hBitmap,sizeof(bm),(LPSTR)&bm);
	
	// Initialize the bitmapinfoheader
	bi.biSize		= sizeof(BITMAPINFOHEADER);
	bi.biWidth		= bm.bmWidth;
	bi.biHeight 		= bm.bmHeight;
	bi.biPlanes 		= 1;
	bi.biBitCount		= bm.bmPlanes * bm.bmBitsPixel;
	bi.biCompression	= dwCompression;
	bi.biSizeImage		= 0;
	bi.biXPelsPerMeter	= 0;
	bi.biYPelsPerMeter	= 0;
	bi.biClrUsed		= 0;
	bi.biClrImportant	= 0;
	
	// Compute the size of the  infoheader and the color table
	int nColors = (1 << bi.biBitCount);
	if( nColors > 256 ) 
		nColors = 0;
	dwLen  = bi.biSize + nColors * sizeof(RGBQUAD);
	
	// We need a device context to get the DIB from
	hDC = GetDC(NULL);
	hPal = SelectPalette(hDC,hPal,FALSE);
	RealizePalette(hDC);
	
	// Allocate enough memory to hold bitmapinfoheader and color table
	hDIB = GlobalAlloc(GMEM_FIXED,dwLen);
	
	if (!hDIB){
		SelectPalette(hDC,hPal,FALSE);
		ReleaseDC(NULL,hDC);
		return NULL;
	}
	
	lpbi = (LPBITMAPINFOHEADER)hDIB;
	
	*lpbi = bi;
	
	// Call GetDIBits with a NULL lpBits param, so the device driver 
	// will calculate the biSizeImage field 
	GetDIBits(hDC, hBitmap, 0L, (DWORD)bi.biHeight,
		(LPBYTE)NULL, (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS);
	
	bi = *lpbi;
	
	// If the driver did not fill in the biSizeImage field, then compute it
	// Each scan line of the image is aligned on a DWORD (32bit) boundary
	if (bi.biSizeImage == 0){
		bi.biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8) 
			* bi.biHeight;
		
		// If a compression scheme is used the result may infact be larger
		// Increase the size to account for this.
		if (dwCompression != BI_RGB)
			bi.biSizeImage = (bi.biSizeImage * 3) / 2;
	}
	
	// Realloc the buffer so that it can hold all the bits
	dwLen += bi.biSizeImage;
	if (handle = GlobalReAlloc(hDIB, dwLen, GMEM_MOVEABLE))
		hDIB = handle;
	else{
		GlobalFree(hDIB);
		
		// Reselect the original palette
		SelectPalette(hDC,hPal,FALSE);
		ReleaseDC(NULL,hDC);
		return NULL;
	}
	
	// Get the bitmap bits
	lpbi = (LPBITMAPINFOHEADER)hDIB;
	
	// FINALLY get the DIB
	BOOL bGotBits = GetDIBits( hDC, hBitmap,
		0L,				// Start scan line
		(DWORD)bi.biHeight,		// # of scan lines
		(LPBYTE)lpbi 			// address for bitmap bits
		+ (bi.biSize + nColors * sizeof(RGBQUAD)),
		(LPBITMAPINFO)lpbi,		// address of bitmapinfo
		(DWORD)DIB_RGB_COLORS);		// Use RGB for color table
	
	if( !bGotBits )
	{
		GlobalFree(hDIB);
		
		SelectPalette(hDC,hPal,FALSE);
		ReleaseDC(NULL,hDC);
		return NULL;
	}
	
	SelectPalette(hDC,hPal,FALSE);
	ReleaseDC(NULL,hDC);
	return hDIB;
}

//////////////////////////////////////////////////////////////////////

BOOL SaveScrJpg::JpegFromDib(HANDLE    hDib,     //Handle to DIB
							 int        nQuality, //JPEG quality (0-100)
							 CString    csJpeg,   //Pathname to jpeg file
							 CString*   pcsMsg)   //Error msg to return
{
    //Basic sanity checks...
    if (nQuality < 0 || nQuality > 100 ||
        hDib   == NULL ||
        pcsMsg == NULL ||
        csJpeg == "")
    {
        if (pcsMsg != NULL)
            *pcsMsg = "Invalid input data";
		
        return FALSE;
    }
	
    *pcsMsg = "";
	
    LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)hDib;
	
//    BYTE *buf2 = 0;
	
    //Use libjpeg functions to write scanlines to disk in JPEG format
    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr       jerr;
	
    FILE*      pOutFile;     //Target file 
    int        nSampsPerRow; //Physical row width in image buffer 
    JSAMPARRAY jsmpArray;    //Pixel RGB buffer for JPEG file
	
    cinfo.err = jpeg_std_error(&jerr); //Use default error handling (ugly!)
	
    jpeg_create_compress(&cinfo);
	
    if ((pOutFile = fopen(csJpeg, "wb")) == NULL)
    {
        *pcsMsg = "Cannot open ";
		*pcsMsg += csJpeg;
        jpeg_destroy_compress(&cinfo);
        return FALSE;
    }
	
    jpeg_stdio_dest(&cinfo, pOutFile);
	
    cinfo.image_width      = lpbi->biWidth;  //Image width and height, in pixels 
    cinfo.image_height     = lpbi->biHeight;
    cinfo.input_components = 3;              //Color components per pixel
	//(RGB_PIXELSIZE - see jmorecfg.h)
    cinfo.in_color_space   = JCS_RGB; 	     //Colorspace of input image
	
    jpeg_set_defaults(&cinfo);
	
    jpeg_set_quality(&cinfo,
		nQuality, //Quality: 0-100 scale
		TRUE);    //Limit to baseline-JPEG values
	
    jpeg_start_compress(&cinfo, TRUE);
	
    //JSAMPLEs per row in output buffer
    nSampsPerRow = cinfo.image_width * cinfo.input_components; 
	
    //Allocate array of pixel RGB values
    jsmpArray = (*cinfo.mem->alloc_sarray)
		((j_common_ptr) &cinfo,
		JPOOL_IMAGE,
		nSampsPerRow,
		cinfo.image_height);
	
    if (DibToSamps(hDib,
		nSampsPerRow,
		cinfo,
		jsmpArray,
		pcsMsg))
    {
        //Write the array of scan lines to the JPEG file
        (void)jpeg_write_scanlines(&cinfo,
			jsmpArray,
			cinfo.image_height);
    }
	
    jpeg_finish_compress(&cinfo); //Always finish
	
	rewind(pOutFile);/**/
	fputc(0x00,pOutFile);
	fputc(0x00,pOutFile);
	
    fclose(pOutFile);
	
    jpeg_destroy_compress(&cinfo); //Free resources
	
    if (*pcsMsg != "")
        return FALSE;
	
    else
        return TRUE;
}

//////////////////////////////////////////////////////////////////////
//This function fills a jsmpArray with the RGB values for the CBitmap.
//It has been improved to handle all legal bitmap formats.
//A jsmpArray is a big array of RGB values, 3 bytes per value.
//Note that rows of pixels are processed bottom to top:
//The data in the jsamp array must be arranged top to bottom.
//////////////////////////////////////////////////////////////////////

BOOL SaveScrJpg::DibToSamps(HANDLE          hDib,
							int				nSampsPerRow,
							struct			jpeg_compress_struct cinfo,
							JSAMPARRAY      jsmpPixels,
							CString*        pcsMsg)
{
	//Sanity...
	if (hDib == NULL || nSampsPerRow <= 0 || pcsMsg == NULL) 
	{ 
		if (pcsMsg !=NULL) 
			*pcsMsg="Invalid input data"; 
		return FALSE; 
	} 
	int r=0, p=0, q=0, b=0, n=0, 
		nUnused=0, nBytesWide=0, nUsed=0, nLastBits=0, nLastNibs=0, nCTEntries=0,
		nRow=0, nByte=0, nPixel=0;
	BYTE bytCTEnt=0;
	LPBITMAPINFOHEADER pbBmHdr= (LPBITMAPINFOHEADER)hDib; //The bit count tells you the format of the bitmap: //Decide how many entries will be in the color table (if any) 
	
	switch (pbBmHdr->biBitCount)
	{
	case 1:
		nCTEntries = 2;   //Monochrome
		break;
		
	case 4:
		nCTEntries = 16;  //16-color
		break;
		
	case 8:
		nCTEntries = 256; //256-color
		break;
		
	case 16:
	case 24:
	case 32:
		nCTEntries = 0;   //No color table needed
		break;
		
	default:
		*pcsMsg = "Invalid bitmap bit count";
		return FALSE; //Unsupported format
	}
	
	//Point to the color table and pixels
	DWORD     dwCTab = (DWORD)pbBmHdr + pbBmHdr->biSize;
	LPRGBQUAD pCTab  = (LPRGBQUAD)(dwCTab);
	LPSTR     lpBits = (LPSTR)pbBmHdr +
		(WORD)pbBmHdr->biSize +
		(WORD)(nCTEntries * sizeof(RGBQUAD));
	
	//Different formats for the image bits
	LPBYTE   lpPixels = (LPBYTE)  lpBits;
	RGBQUAD* pRgbQs   = (RGBQUAD*)lpBits;
	WORD*    wPixels  = (WORD*)   lpBits;
	
	//Set up the jsamps according to the bitmap's format.
	//Note that rows are processed bottom to top, because
	//that's how bitmaps are created.
	switch (pbBmHdr->biBitCount)
	{
	case 1:
		nUsed      = (pbBmHdr->biWidth + 7) / 8;
		nUnused    = (((nUsed + 3) / 4) * 4) - nUsed;
		nBytesWide = nUsed + nUnused;
		nLastBits  = 8 - ((nUsed * 8) - pbBmHdr->biWidth);
		
		for (r=0; r < pbBmHdr->biHeight; r++)
		{
            for (p=0,q=0; p < nUsed; p++) 
            { 
				nRow=(pbBmHdr->biHeight-r-1) * nBytesWide;
				nByte =  nRow + p;
				
				int nBUsed = (p <(nUsed - 1)) ? 8 : nLastBits; 
				for(b=0; b < nBUsed; b++) 
				{ 
					bytCTEnt = lpPixels[nByte] << b; 
					bytCTEnt = bytCTEnt >> 7;
					
					jsmpPixels[r][q+0] = pCTab[bytCTEnt].rgbRed;
					jsmpPixels[r][q+1] = pCTab[bytCTEnt].rgbGreen;
					jsmpPixels[r][q+2] = pCTab[bytCTEnt].rgbBlue;
					
					q += 3;
				}
            }
		}
		break;
		
	case 4:
		nUsed      = (pbBmHdr->biWidth + 1) / 2;
		nUnused    = (((nUsed + 3) / 4) * 4) - nUsed;
		nBytesWide = nUsed + nUnused;
		nLastNibs  = 2 - ((nUsed * 2) - pbBmHdr->biWidth);
		
		for (r=0; r < pbBmHdr->biHeight;r++)
		{
            for (p=0,q=0; p < nUsed;p++) 
            { 
				nRow=(pbBmHdr->biHeight-r-1) * nBytesWide;
				nByte = nRow + p;
							
				jsmpPixels[r][q+0] = pCTab[bytCTEnt].rgbRed;
				jsmpPixels[r][q+1] = pCTab[bytCTEnt].rgbGreen;
				jsmpPixels[r][q+2] = pCTab[bytCTEnt].rgbBlue;
				
				q += 3;
			}
		}
		break;
		
	case 8: //Each byte is a pointer to a pixel color
		nUnused = (((pbBmHdr->biWidth + 3) / 4) * 4) -
			pbBmHdr->biWidth;
		
		for (r=0;r < pbBmHdr->biHeight; r++)
		{
            for (p=0,q=0; p < pbBmHdr->biWidth; p++,q+=3)
            {
				nRow   = (pbBmHdr->biHeight-r-1) * (pbBmHdr->biWidth + nUnused);
				nPixel =  nRow + p;
				
				jsmpPixels[r][q+0] = pCTab[lpPixels[nPixel]].rgbRed;
				jsmpPixels[r][q+1] = pCTab[lpPixels[nPixel]].rgbGreen;
				jsmpPixels[r][q+2] = pCTab[lpPixels[nPixel]].rgbBlue;
            }
		}
		break;
		
	case 16: //Hi-color (16 bits per pixel)
		for (r=0;r < pbBmHdr->biHeight; r++)
		{
            for (p=0,q=0; p < pbBmHdr->biWidth; p++,q+=3)
            {
				nRow    = (pbBmHdr->biHeight-r-1) * pbBmHdr->biWidth;
				nPixel  = nRow + p;
				
				RGBQUAD quad = QuadFromWord(wPixels[nPixel]);
				
				jsmpPixels[r][q+0] = quad.rgbRed;
				jsmpPixels[r][q+1] = quad.rgbGreen;
				jsmpPixels[r][q+2] = quad.rgbBlue;
            }
		}
		break;
		
	case 24:
		nBytesWide =  (pbBmHdr->biWidth*3);
		nUnused    =  (((nBytesWide + 3) / 4) * 4) -
			nBytesWide;
		nBytesWide += nUnused;
		
		for (r=0;r<pbBmHdr->biHeight;r++)
		{
            for (p=0,q=0;p < (nBytesWide-nUnused); p+=3,q+=3)
            { 
				nRow = (pbBmHdr->biHeight-r-1) * nBytesWide;
				nPixel  = nRow + p;
				
				jsmpPixels[r][q+0] = lpPixels[nPixel+2]; //Red
				jsmpPixels[r][q+1] = lpPixels[nPixel+1]; //Green
				jsmpPixels[r][q+2] = lpPixels[nPixel+0]; //Blue
            }
		}
		break;
		
	case 32:
		for (r=0; r < pbBmHdr->biHeight; r++)
		{
            for (p=0,q=0; p < pbBmHdr->biWidth; p++,q+=3)
            {
				nRow    = (pbBmHdr->biHeight-r-1) *
					pbBmHdr->biWidth;
				nPixel  = nRow + p;
				
				jsmpPixels[r][q+0] = pRgbQs[nPixel].rgbRed;
				jsmpPixels[r][q+1] = pRgbQs[nPixel].rgbGreen;
				jsmpPixels[r][q+2] = pRgbQs[nPixel].rgbBlue;
            }
		}
		break;
   }   //end switch
   
   return TRUE;
}

//////////////////////////////////////////////////////////////////////
//This function turns a 16-bit pixel
//into an RGBQUAD value.
//////////////////////////////////////////////////////////////////////
RGBQUAD SaveScrJpg::QuadFromWord(WORD b16)
{
	BYTE bytVals[] =
	{
		0,  16, 24, 32,  40, 48, 56, 64,
			72, 80, 88, 96, 104,112,120,128,
			136,144,152,160,168,176,184,192,
			200,208,216,224,232,240,248,255
	};
	
	WORD wR = b16;
	WORD wG = b16;
	WORD wB = b16;
	
	wR <<= 1; wR >>= 11;
	wG <<= 6; wG >>= 11;
	wB <<= 11; wB >>= 11;
	
	RGBQUAD rgb;
	
	rgb.rgbReserved = 0;
	rgb.rgbBlue     = bytVals[wB];
	rgb.rgbGreen    = bytVals[wG];
	rgb.rgbRed      = bytVals[wR];
	
	return rgb;
}

//////////////////////////////////////////////////////////////////////

SaveScrJpg::SaveScrJpg()
{
	strcpy(SaveAddr,"C:" );
}

//////////////////////////////////////////////////////////////////////

SaveScrJpg::~SaveScrJpg()
{
	
}

//////////////////////////////////////////////////////////////////////

void SaveScrJpg::SaveScreen(int jpgOrder)
{
	HDC         hScrDC, hMemDC;         
	HBITMAP     hBitmap, hOldBitmap;    
	int         nX, nY, nX2, nY2;       
	int         nWidth, nHeight;        
	int         xScrn, yScrn;  
	CString one;
	hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);     
	hMemDC = CreateCompatibleDC(hScrDC);      
	nX = 0;
	nY = 0;
	nX2 =GetDeviceCaps(hScrDC, HORZRES);
	nY2 =GetDeviceCaps(hScrDC, VERTRES);
	/// get screen resolution      
	xScrn =GetDeviceCaps(hScrDC, HORZRES);     
	yScrn =GetDeviceCaps(hScrDC, VERTRES);      
	//make sure bitmap rectangle is visible      
	if (nX < 0)         
		nX = 0;     
	if (nY < 0)         
		nY = 0;     
	if (nX2 > xScrn)         
		nX2 = xScrn;     
	if (nY2 > yScrn)         
		nY2 = yScrn;      
	nWidth = nX2 - nX;    
	nHeight = nY2 - nY;      
	// create a bitmap compatible with the screen DC     
	hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight);   
	hOldBitmap =(HBITMAP) SelectObject(hMemDC, hBitmap);      
	BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY); 
	
	
	HANDLE hDib=DDBToDIB( hBitmap, BI_RGB, NULL);
    CString  csMsg = "";
	
	CString RealSaveName;
	RealSaveName.Format("%s\\%d.jpg",SaveAddr,jpgOrder);
    if (hDib != NULL)
    {
        if (!JpegFromDib(hDib,
			45,   //画面质量 0-100
			RealSaveName,&csMsg))
            ::MessageBox(NULL,csMsg,NULL,MB_OK);
        else
			::GlobalFree(hDib);
    }
    else
        ::MessageBox(NULL,"Failed to load IDB_TEST",NULL,MB_OK);
    ::SelectObject(hMemDC,hOldBitmap);
	::DeleteObject(hBitmap);
	::DeleteDC(hScrDC);
	::DeleteDC(hMemDC);
}

//////////////////////////////////////////////////////////////////////